Skip to content

feat(customcurrencies): support custom currency credit purchases#4773

Merged
turip merged 1 commit into
mainfrom
feat/custom-currency-credit-purchases
Jul 23, 2026
Merged

feat(customcurrencies): support custom currency credit purchases#4773
turip merged 1 commit into
mainfrom
feat/custom-currency-credit-purchases

Conversation

@turip

@turip turip commented Jul 23, 2026

Copy link
Copy Markdown
Member

What this unlocks

Custom-currency credit purchases can now move through the charges and billing flow while settling in fiat. The purchase keeps its credit currency and amount, while the generated invoice line carries the converted fiat total needed by billing.

This establishes the charges-side contract needed for the ledger integration to follow: custom-currency purchases remain disabled by default and return the usual unsupported error until downstream support is enabled explicitly.

It also makes the custom-currency gate consistent across flat-fee, usage-based, and credit-purchase charge creation, so rollout can happen without allowing unsupported charge shapes through another settlement mode.

Summary by CodeRabbit

  • New Features

    • Enabled more accurate credit-purchase settlement handling by separating purchased credit currency from fiat settlement currency.
    • Gathering line names now include the purchased credit amount and currency code.
  • Bug Fixes

    • Custom-currency purchases are now consistently rejected when custom-currency support is disabled (across supported charge types).
    • Improved currency validation for fiat settlement codes and rounding behavior in invoice-based flows.
  • Tests

    • Expanded coverage for custom/fiat currency behavior, validation failures, and JSON round-trip preservation.

Greptile Summary

Custom-currency credit purchases can now retain their purchased currency while settling invoice and external payments in fiat.

  • Adds a default-disabled custom-currency gate across credit-purchase, flat-fee, and usage-based charge creation.
  • Changes credit-purchase settlement currency to an explicit fiat type and converts purchased credits into fiat gathering-line totals.
  • Expands tests for validation, persistence, settlement serialization, and custom-currency invoice flows.

Confidence Score: 5/5

The PR appears safe to merge because no eligible blocking failures remain.

No blocking failure remains.

Important Files Changed

Filename Overview
openmeter/billing/charges/creditpurchase/charge.go Allows fiat settlement currency to differ from the purchased currency when the latter is custom.
openmeter/billing/charges/creditpurchase/service/create.go Applies the custom-currency gate and creates fiat-denominated gathering lines for custom-currency purchases.
openmeter/billing/charges/creditpurchase/service/service.go Adds the default-disabled atomic custom-currency feature switch used by tests.
openmeter/billing/charges/creditpurchase/settlement.go Narrows settlement currency from a generic currency code to an explicit fiat code.
openmeter/billing/charges/flatfee/service/create.go Applies the custom-currency gate consistently across all flat-fee settlement modes.
openmeter/billing/charges/usagebased/service/create.go Applies the custom-currency gate consistently across all usage-based settlement modes.
openmeter/billing/creditgrant/service/service.go Maps credit-grant purchase settlement currencies into the new fiat settlement type.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Purchase[Custom-currency credit purchase] --> Gate{Custom currency enabled?}
  Gate -->|No| Unsupported[Return unsupported error]
  Gate -->|Yes| Charge[Create charge in purchased currency]
  Charge --> Conversion[Multiply credit amount by cost basis]
  Conversion --> FiatLine[Create gathering line in settlement fiat]
  FiatLine --> Invoice[Billing invoice flow]
Loading

Reviews (4): Last reviewed commit: "feat(customcurrencies): support credit p..." | Re-trigger Greptile

Context used:

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Custom-currency handling now uses explicit enablement in charge services, separates purchased credit currencies from fiat settlement currencies, updates invoice gathering-line construction, and expands validation and integration test coverage.

Changes

Custom currency settlement handling

Layer / File(s) Summary
Currency contracts and validation
openmeter/billing/charges/creditpurchase/{charge.go,settlement.go}, openmeter/billing/charges/creditpurchase/settlement_test.go
Settlement currencies use currencyx.FiatCode, validation normalizes comparisons, and tests cover invalid fiat codes and JSON round trips.
Custom currency gating
openmeter/billing/charges/{flatfee,usagebased,creditpurchase}/service/*, openmeter/billing/charges/service/*costbasis_test.go, openmeter/billing/charges/service/invoicable_test.go
Custom currencies are rejected by default and enabled explicitly through test helpers.
Invoice credit purchase flow
openmeter/billing/charges/creditpurchase/service/*, openmeter/billing/charges/service/creditpurchase_test.go
Invoice gathering lines use fiat settlement rounding and currency, include credit amount and currency in the resource name, and validate enabled and disabled flows.
Fiat settlement propagation and guidance
openmeter/billing/creditgrant/service/service.go, openmeter/ledger/**/*test.go, test/credits/*, .agents/skills/charges/SKILL.md
Settlement construction and fixtures use typed fiat currencies, with documentation describing purchased-credit and settlement-currency handling.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TestSuite
  participant CreditPurchaseService
  participant ChargeStore
  participant GatheringLine
  TestSuite->>CreditPurchaseService: Create custom-currency intent
  CreditPurchaseService->>CreditPurchaseService: Check custom-currency enablement
  CreditPurchaseService->>GatheringLine: Build fiat-priced invoice line
  CreditPurchaseService->>ChargeStore: Persist charge and settlement
  ChargeStore-->>TestSuite: Return persisted charge
Loading

Possibly related PRs

Suggested labels: release-note/feature, area/billing

Suggested reviewers: tothandras, mark-vass-konghq

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: enabling custom currency credit purchases.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/custom-currency-credit-purchases

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Base automatically changed from feat/custom-currency-cost-basis-resolution to main July 23, 2026 08:00
@turip
turip force-pushed the feat/custom-currency-credit-purchases branch from 61a5e64 to 33612da Compare July 23, 2026 08:05
@turip
turip marked this pull request as ready for review July 23, 2026 08:09
@turip
turip requested a review from a team as a code owner July 23, 2026 08:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
openmeter/billing/charges/creditpurchase/service/create.go (1)

24-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Same custom-currency gate copy-pasted three times. Since this PR is unifying the gate across flat-fee, usage-based, and credit-purchase creation anyway, it's a great moment to pull the shared IsCustom() && !enabled check + error wrap into one small helper (e.g. in the meta package) instead of hand-copying it.

  • openmeter/billing/charges/creditpurchase/service/create.go#L24-L24: replace the inline guard with a call to the shared helper, passing the credit-purchase-specific error message/action text.
  • openmeter/billing/charges/flatfee/service/create.go#L35-L35: same swap for the flat-fee guard.
  • openmeter/billing/charges/usagebased/service/create.go#L34-L34: same swap for the usage-based guard.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/billing/charges/creditpurchase/service/create.go` at line 24, The
custom-currency eligibility check and wrapped error are duplicated across the
creation services; extract them into one shared helper, such as in the meta
package, accepting the currency and operation-specific error/action text. Update
openmeter/billing/charges/creditpurchase/service/create.go:24,
openmeter/billing/charges/flatfee/service/create.go:35, and
openmeter/billing/charges/usagebased/service/create.go:34 to call that helper
with their respective messages, preserving the existing gate behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@openmeter/billing/charges/creditpurchase/service/create.go`:
- Line 24: The custom-currency eligibility check and wrapped error are
duplicated across the creation services; extract them into one shared helper,
such as in the meta package, accepting the currency and operation-specific
error/action text. Update
openmeter/billing/charges/creditpurchase/service/create.go:24,
openmeter/billing/charges/flatfee/service/create.go:35, and
openmeter/billing/charges/usagebased/service/create.go:34 to call that helper
with their respective messages, preserving the existing gate behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 17f249f2-cf0b-4659-9ec4-347b266d717d

📥 Commits

Reviewing files that changed from the base of the PR and between 7e5a848 and 33612da.

📒 Files selected for processing (22)
  • .agents/skills/charges/SKILL.md
  • openmeter/billing/charges/creditpurchase/charge.go
  • openmeter/billing/charges/creditpurchase/service/create.go
  • openmeter/billing/charges/creditpurchase/service/external_test.go
  • openmeter/billing/charges/creditpurchase/service/service.go
  • openmeter/billing/charges/creditpurchase/settlement.go
  • openmeter/billing/charges/creditpurchase/settlement_test.go
  • openmeter/billing/charges/flatfee/service/create.go
  • openmeter/billing/charges/service/creditpurchase_test.go
  • openmeter/billing/charges/service/flatfee_costbasis_test.go
  • openmeter/billing/charges/service/invoicable_test.go
  • openmeter/billing/charges/service/taxcode_test.go
  • openmeter/billing/charges/service/usagebased_costbasis_test.go
  • openmeter/billing/charges/usagebased/service/create.go
  • openmeter/billing/creditgrant/service/service.go
  • openmeter/ledger/chargeadapter/creditpurchase_test.go
  • openmeter/ledger/customerbalance/service_test.go
  • openmeter/ledger/customerbalance/testenv_test.go
  • test/app/stripe/invoice_credits_test.go
  • test/credits/credit_then_invoice_test.go
  • test/credits/sanity_lifecycle_test.go
  • test/credits/sanity_test.go

@turip
turip force-pushed the feat/custom-currency-credit-purchases branch from 33612da to ba556a2 Compare July 23, 2026 10:01
@turip turip added release-note/feature Release note: Exciting New Features area/billing labels Jul 23, 2026
@turip
turip enabled auto-merge (squash) July 23, 2026 10:07
@turip
turip merged commit 6357f12 into main Jul 23, 2026
29 of 31 checks passed
@turip
turip deleted the feat/custom-currency-credit-purchases branch July 23, 2026 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/billing release-note/feature Release note: Exciting New Features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants